home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 701-725 / 708 / intuisup / intuisup42.lha / Intuisup / source.lha / Gadgets / gadgets2.c < prev    next >
C/C++ Source or Header  |  1992-06-23  |  48KB  |  1,470 lines

  1. /* $Revision Header *** Header built automatically - do not edit! ***********
  2.  *
  3.  *    (C) Copyright 1991 by Torsten Jürgeleit
  4.  *
  5.  *    Name .....: gadgets2.c
  6.  *    Created ..: Thursday 19-Dec-91 20:52:53
  7.  *    Revision .: 4
  8.  *
  9.  *    Date        Author                 Comment
  10.  *    =========   ====================   ====================
  11.  *    23-Apr-92   Torsten Jürgeleit      now all PRINTABLE characters can
  12.  *                                         be used as hotkeys
  13.  *    01-Apr-92   Torsten Jürgeleit      any references to gadget data
  14.  *                                         via gl_Data removed
  15.  *    25-Mar-92   Torsten Jürgeleit      now the ASCII chars `!'..`/' and
  16.  *                                         `:'..`@' can be used as hotkeys
  17.  *    05-Jan-92   Torsten Jürgeleit      now try to open font before
  18.  *                                         initializing gadget;
  19.  *                                         correct display of larger fonts
  20.  *                                         for mutual exclude gadgets
  21.  *    19-Dec-91   Torsten Jürgeleit      Created this file!
  22.  *
  23.  ****************************************************************************
  24.  *
  25.  *    Gadget support routines - part 2
  26.  *
  27.  * $Revision Header ********************************************************/
  28.  
  29.     /* Includes */
  30.  
  31. #include <exec/types.h>
  32. #include <exec/memory.h>
  33. #include <devices/inputevent.h>
  34. #include <intuition/intuition.h>
  35. #ifdef AZTEC_C
  36. #include <functions.h>   /* needed for Aztec C - prototypes and pragmas for all Amiga system functions */
  37. #endif
  38. #include <libraries/memwatch.h>   /* header file for memory debug link library (Fish 240) - AFTER functions.h */
  39. #include <string.h>
  40. #include "/render/render.h"
  41. #include "/texts/texts.h"
  42. #include "/borders/borders.h"
  43. #include "/language/language.h"
  44. #include "gadgets.h"
  45. #include "imports.h"
  46.  
  47.     /* Count entries in gadget data array */
  48.  
  49.    USHORT
  50. count_gadget_data_entries(struct GadgetData  *gd)
  51. {
  52.    USHORT data_entries = 0;
  53.  
  54.    while (gd->gd_Type != INTUISUP_DATA_END &&
  55.                       gd->gd_Type <= MAX_GADGET_DATA_TYPE) {
  56.       data_entries++;
  57.       gd++;
  58.    }
  59.    return(data_entries);
  60. }
  61.     /* Get buffer size for gadgets and borders */
  62.  
  63.    ULONG
  64. get_gadget_buffer_size(struct GadgetList  *gl, struct GadgetData  *gd)
  65. {
  66.    struct RenderInfo  *ri = gl->gl_RenderInfo;
  67.    USHORT i, data_entries = gl->gl_DataEntries;
  68.    ULONG  buffer_size = 0;
  69.  
  70.    for (i = 0; i < data_entries; i++, gd++) {
  71.       BYTE   **text;
  72.       USHORT gadget_size, border_size, num, height, spacing,
  73.          type = gd->gd_Type;
  74.       ULONG  flags = gd->gd_Flags;
  75.  
  76.       /* If monochrome display then set HIGHCOMP flag */
  77.       if (ri->ri_ScreenDepth == 1) {
  78.      flags |= GADGET_DATA_FLAG_HIGH_COMP;
  79.       }
  80.       switch(type) {
  81.      case GADGET_DATA_TYPE_BUTTON :
  82.         gadget_size = sizeof(struct ExtendedGadget);
  83.         if ((flags & GADGET_DATA_FLAG_BUTTON_TOGGLE &&
  84.                    flags & GADGET_DATA_FLAG_BUTTON_IMAGE) ||
  85.                        flags & GADGET_DATA_FLAG_HIGH_COMP) {
  86.            border_size = BORDER_TYPE_BOX1_BUFFER_SIZE;
  87.         } else {
  88.            border_size = 2 * BORDER_TYPE_BOX1_BUFFER_SIZE;
  89.         }
  90.  
  91.         /* Add image struct size if chip mem copies of image data needed */
  92.         if (gd->gd_Flags & GADGET_DATA_FLAG_BUTTON_IMAGE) {
  93.            struct Image  *image;
  94.  
  95.            if ((image = gd->gd_SpecialData.gd_ButtonData.gd_ButtonNormalRender) &&
  96.                        check_gadget_image(image) == FALSE) {
  97.           buffer_size += sizeof(struct Image);
  98.            }
  99.            if ((image = gd->gd_SpecialData.gd_ButtonData.gd_ButtonSelectRender) &&
  100.                        check_gadget_image(image) == FALSE) {
  101.           buffer_size += sizeof(struct Image);
  102.            }
  103.         }
  104.         break;
  105.  
  106.      case GADGET_DATA_TYPE_CHECK :
  107.         gadget_size = sizeof(struct ExtendedGadget);
  108.         border_size = BORDER_TYPE_BOX1_BUFFER_SIZE;
  109.         break;
  110.  
  111.      case GADGET_DATA_TYPE_MX :
  112.         text = gd->gd_SpecialData.gd_MXData.gd_MXTextArray;
  113.         num  = 0;
  114.         while (*text++) {
  115.            num++;
  116.         }
  117.         gadget_size = num * (sizeof(struct ExtendedGadget) +
  118.               sizeof(struct IntuiText)) + sizeof(struct MXData);
  119.         border_size = BORDER_TYPE_BOX1_BUFFER_SIZE;
  120.         break;
  121.  
  122.      case GADGET_DATA_TYPE_STRING :
  123.      case GADGET_DATA_TYPE_INTEGER :
  124.  
  125.         /* Calc size of input buffer */
  126.         if (type == GADGET_DATA_TYPE_STRING) {
  127.            num = gd->gd_SpecialData.gd_InputData.gd_InputLen;
  128.            if (flags & (GADGET_DATA_FLAG_STRING_UNSIGNED_DEC |
  129.                     GADGET_DATA_FLAG_STRING_SIGNED_DEC |
  130.                            GADGET_DATA_FLAG_STRING_HEX |
  131.                          GADGET_DATA_FLAG_STRING_BIN)) {
  132.           if (num < (MAX_BIN_NUM_DIGITS + 1)) {
  133.              num = MAX_BIN_NUM_DIGITS + 1;   /* identifier `%' + number */
  134.           }
  135.            }
  136.         } else {
  137.            num = MAX_DEC_NUM_DIGITS;
  138.         }
  139.         if (num & 1) {   /* odd input len ? */
  140.            num += 1;
  141.         } else {
  142.            num += 2;   /* inc for end of string marker */
  143.         }
  144.         gadget_size = sizeof(struct ExtendedGadget) +
  145.          sizeof(struct StringInfo) + num + sizeof(struct InputData);
  146.         border_size = BORDER_TYPE_BOX2_BUFFER_SIZE;
  147.         break;
  148.  
  149.      case GADGET_DATA_TYPE_SLIDER :
  150.         gadget_size = sizeof(struct ExtendedGadget) +
  151.                 sizeof(struct PropInfo) + sizeof(struct Image) +
  152.                           sizeof(struct SliderData);
  153.         border_size = BORDER_TYPE_BOX1_BUFFER_SIZE;
  154.         break;
  155.  
  156.      case GADGET_DATA_TYPE_SCROLLER :
  157.         if (flags & GADGET_DATA_FLAG_SCROLLER_NO_ARROWS) {
  158.            gadget_size = sizeof(struct ExtendedGadget) +
  159.                 sizeof(struct PropInfo) + sizeof(struct Image) +
  160.                         sizeof(struct ScrollerData);
  161.            border_size = BORDER_TYPE_BOX1_BUFFER_SIZE;
  162.         } else {
  163.            gadget_size = 3 * sizeof(struct ExtendedGadget) +
  164.                 sizeof(struct PropInfo) + sizeof(struct Image) +
  165.                         sizeof(struct ScrollerData);
  166.            if (flags & GADGET_DATA_FLAG_HIGH_COMP) {
  167.           border_size = 3 * BORDER_TYPE_BOX1_BUFFER_SIZE;
  168.            } else {
  169.           border_size = 5 * BORDER_TYPE_BOX1_BUFFER_SIZE;
  170.            }
  171.         }
  172.         break;
  173.  
  174.      case GADGET_DATA_TYPE_CYCLE :
  175.         gadget_size = sizeof(struct ExtendedGadget) +
  176.                            sizeof(struct CycleData);
  177.         if (flags & GADGET_DATA_FLAG_HIGH_COMP) {
  178.            border_size = BORDER_TYPE_BOX1_BUFFER_SIZE;
  179.         } else {
  180.            border_size = 2 * BORDER_TYPE_BOX1_BUFFER_SIZE;
  181.         }
  182.         break;
  183.  
  184.      case GADGET_DATA_TYPE_COUNT :
  185.         gadget_size = sizeof(struct ExtendedGadget) +
  186.                            sizeof(struct CountData);
  187.         border_size = 2 * BORDER_TYPE_BOX1_BUFFER_SIZE;
  188.         break;
  189.  
  190.      case GADGET_DATA_TYPE_LISTVIEW :
  191.         if (flags & GADGET_DATA_FLAG_LISTVIEW_READ_ONLY) {
  192.            num = 0;
  193.         } else {
  194.            struct TextAttr  *ta;
  195.  
  196.            if (!(ta = gd->gd_TextAttr)) {
  197.           ta = &gl->gl_RenderInfo->ri_TextAttr;
  198.            }
  199.            height  = gd->gd_Height;
  200.            spacing = gd->gd_SpecialData.gd_ListViewData.gd_ListViewSpacing;
  201.            if (!(flags & GADGET_DATA_FLAG_NO_BORDER)) {
  202.           height -= 2 * 1;
  203.            }
  204.            num = (height + spacing) / (ta->ta_YSize + spacing);
  205.         }
  206.         gadget_size = (3 + num) * sizeof(struct ExtendedGadget) +
  207.                 sizeof(struct PropInfo) + sizeof(struct Image) +
  208.                         sizeof(struct ListViewData);
  209.         if (flags & GADGET_DATA_FLAG_HIGH_COMP) {
  210.            border_size = 4 * BORDER_TYPE_BOX1_BUFFER_SIZE;
  211.         } else {
  212.            border_size = 6 * BORDER_TYPE_BOX1_BUFFER_SIZE;
  213.         }
  214.         break;
  215.  
  216.      case GADGET_DATA_TYPE_PALETTE :
  217.         num         = 1L << gd->gd_SpecialData.gd_PaletteData.gd_PaletteDepth;
  218.         gadget_size = num * (sizeof(struct ExtendedGadget) +
  219.              sizeof(struct Image)) + sizeof(struct PaletteData);
  220.         if (flags & GADGET_DATA_FLAG_HIGH_COMP) {
  221.            border_size = num * BORDER_TYPE_BOX1_BUFFER_SIZE;
  222.         } else {
  223.            border_size = num * (2 * BORDER_TYPE_BOX1_BUFFER_SIZE);
  224.         }
  225.         if (!(flags & GADGET_DATA_FLAG_PALETTE_NO_INDICATOR)) {
  226.            gadget_size += sizeof(struct ExtendedGadget) +
  227.                                sizeof(struct Image);
  228.            border_size += BORDER_TYPE_BOX1_BUFFER_SIZE;
  229.         }
  230.         break;
  231.       }
  232.       buffer_size += gadget_size;
  233.       if (!(flags & GADGET_DATA_FLAG_NO_BORDER)) {
  234.      buffer_size += border_size;
  235.       }
  236.    }
  237.    return(buffer_size);
  238. }
  239.     /* Get buffer size for image data */
  240.  
  241.    ULONG
  242. get_image_buffer_size(struct GadgetList  *gl, struct GadgetData  *gd)
  243. {
  244.    USHORT i, data_entries = gl->gl_DataEntries;
  245.    ULONG  buffer_size = 0;
  246.  
  247.    for (i = 0; i < data_entries; i++, gd++) {
  248.       if (gd->gd_Type == GADGET_DATA_TYPE_BUTTON &&
  249.                (gd->gd_Flags & GADGET_DATA_FLAG_BUTTON_IMAGE)) {
  250.      struct Image  *image;
  251.  
  252.      if ((image = gd->gd_SpecialData.gd_ButtonData.gd_ButtonNormalRender) &&
  253.                        check_gadget_image(image) == FALSE) {
  254.         buffer_size += (image->Width / 16 + (image->Width & 15 ? 1 : 0))
  255.                      * image->Height * image->Depth * 2;
  256.      }
  257.      if ((image = gd->gd_SpecialData.gd_ButtonData.gd_ButtonSelectRender) &&
  258.                        check_gadget_image(image) == FALSE) {
  259.         buffer_size += (image->Width / 16 + (image->Width & 15 ? 1 : 0))
  260.                      * image->Height * image->Depth * 2;
  261.      }
  262.       }
  263.    }
  264.    return(buffer_size);
  265. }
  266.     /* Initialize gadgets from gadget list */
  267.  
  268.    VOID
  269. init_gadgets(struct GadgetList  *gl, struct GadgetData  *gd,
  270.                            SHORT hoffset, SHORT voffset)
  271. {
  272.    struct RenderInfo  *ri = gl->gl_RenderInfo;
  273.    BYTE   *buffer = gl->gl_GadgetBuffer, *image_buffer = gl->gl_ImageBuffer;
  274.    USHORT i, data_entries = gl->gl_DataEntries;
  275.  
  276.    for (i = 0; i < data_entries; i++, gd++) {
  277.       struct ExtendedGadget  *egad, *first_egad;
  278.       struct Image           *image;
  279.       struct IntuiText       itext;
  280.       struct MXData          *mx;
  281.       struct InputData       *id;
  282.       struct SliderData      *sl;
  283.       struct ScrollerData    *sc;
  284.       struct CycleData       *cy;
  285.       struct CountData       *co;
  286.       struct ListViewData    *lv;
  287.       struct PaletteData     *pd;
  288.       struct TextAttr        *ta;
  289.       struct TextFont        *tf;
  290.       BYTE   **text;
  291.       USHORT j, max_width, num, len, xoffset, yoffset, xmin, ymin,
  292.          xnum, ynum, yinc, spacing, text_height,
  293.          type = gd->gd_Type, left_edge = gd->gd_LeftEdge + hoffset,
  294.          top_edge = gd->gd_TopEdge + voffset, width = gd->gd_Width,
  295.          height = gd->gd_Height;
  296.       ULONG  min, max, flags = gd->gd_Flags;
  297.  
  298.       /* Get ptr to extended gadget and reserve buffer */
  299.       egad    = gl->gl_Gadgets[i] = (struct ExtendedGadget *)buffer;
  300.       buffer += sizeof(struct ExtendedGadget);
  301.  
  302.       /* Save ptr to first gadget of ISUP object */
  303.       first_egad = egad;
  304.  
  305.       /* Save absolut gadget position - needed by modify_gadget() */
  306.       egad->eg_BorderLeftEdge = left_edge;
  307.       egad->eg_BorderTopEdge  = top_edge;
  308.       egad->eg_DataFlags      = flags;
  309.  
  310.       /* Open text font and save data */
  311.       if (!(ta = gd->gd_TextAttr) || !(ta = ask_font(ri, ta))) {
  312.      ta = &ri->ri_TextAttr;
  313.      tf = ri->ri_TextFont;
  314.       } else {
  315.      if (!(tf = open_font(ri, ta))) {
  316.         ta = &ri->ri_TextAttr;
  317.         tf = ri->ri_TextFont;
  318.      } else {
  319.         egad->eg_Flags |= EXTENDED_GADGET_FLAG_CLOSE_FONT;
  320.      }
  321.       }
  322.       egad->eg_TextAttr = ta;
  323.       egad->eg_TextFont = tf;
  324.       text_height       = ta->ta_YSize;
  325.  
  326.       /* Init intui text */
  327.       itext.ITextFont = ta;
  328.  
  329.       /* Calc border offsets */
  330.       if (flags & GADGET_DATA_FLAG_NO_BORDER) {
  331.      xoffset = 0;
  332.      yoffset = 0;
  333.       } else {
  334.      switch (type) {
  335.         case GADGET_DATA_TYPE_MX :
  336.            xoffset = 8;
  337.            yoffset = 4;
  338.            break;
  339.  
  340.         case GADGET_DATA_TYPE_STRING :
  341.         case GADGET_DATA_TYPE_INTEGER :
  342.            xoffset = 6;
  343.            yoffset = 3;
  344.            break;
  345.  
  346.         case GADGET_DATA_TYPE_CYCLE :
  347.         case GADGET_DATA_TYPE_COUNT :
  348.            xoffset = 2;
  349.            yoffset = 1;
  350.            break;
  351.  
  352.         default :
  353.            xoffset = 4;
  354.            yoffset = 2;
  355.            break;
  356.      }
  357.       }
  358.  
  359.       /* Inner window position needed ? */
  360.       if (ri->ri_Flags & RENDER_INFO_FLAG_INNER_WINDOW) {
  361.      left_edge += ri->ri_WindowBorderLeft;
  362.      top_edge  += ri->ri_WindowBorderTop;
  363.       }
  364.  
  365.       /* If fixed gadget dimensions or data buffers so init them yet */
  366.       switch (type) {
  367.      case GADGET_DATA_TYPE_CHECK :
  368.  
  369.         /* Calc fixed dimensions of check gadget */
  370.         width  = IMAGE_CHECK_WIDTH + 2 * IMAGE_HORIZ_OFFSET;
  371.         height = IMAGE_CHECK_HEIGHT + 2 * IMAGE_VERT_OFFSET;
  372.         break;
  373.  
  374.      case GADGET_DATA_TYPE_MX :
  375.  
  376.         /* Calc fixed dimensions of mx gadget */
  377.         width  = IMAGE_KNOB_WIDTH;
  378.         height = IMAGE_KNOB_HEIGHT;
  379.  
  380.         /* Calc vertical offset between mx gadget */
  381.         if ((yinc = text_height) < height) {
  382.            yinc = height;
  383.         }
  384.         yinc += gd->gd_SpecialData.gd_MXData.gd_MXSpacing;
  385.  
  386.         /* Count mx gadgets and calc maximal text width */
  387.         text      = gd->gd_SpecialData.gd_MXData.gd_MXTextArray;
  388.         num       = 0;
  389.         max_width = 0;
  390.         while (*text) {
  391.            itext.IText = (UBYTE *)get_language_text(*text++,
  392.                           gl->gl_LanguageTextArray);
  393.            if ((len = IntuiTextLength(&itext)) > max_width) {
  394.           max_width = len;
  395.            }
  396.            num++;
  397.         }
  398.  
  399.         /* Left and top edge of gadget */
  400.         if (flags & GADGET_DATA_FLAG_TEXT_LEFT) {
  401.            left_edge += max_width + xoffset + 8;
  402.         } else {
  403.            left_edge += xoffset;
  404.         }
  405.         if (text_height > height) {
  406.            top_edge += (text_height - height) / 2 + yoffset;
  407.         } else {
  408.            top_edge += yoffset;
  409.         }
  410.  
  411.         /* Init mx data */
  412.         mx                 = (struct MXData *)buffer;
  413.         buffer            += sizeof(struct MXData);
  414.         mx->mx_TextEntries = num;
  415.         break;
  416.  
  417.      case GADGET_DATA_TYPE_STRING :
  418.      case GADGET_DATA_TYPE_INTEGER :
  419.  
  420.         /* Calc fixed height of input gadgets */
  421.         height = ri->ri_TextAttr.ta_YSize + 2 * yoffset;
  422.  
  423.         /* Init input data */
  424.         id                  = (struct InputData *)buffer;
  425.         buffer             += sizeof(struct InputData);
  426.         id->id_ActivateNext = gd->gd_SpecialData.gd_InputData.gd_InputActivateNext;
  427.         id->id_ActivatePrev = gd->gd_SpecialData.gd_InputData.gd_InputActivatePrev;
  428.         break;
  429.  
  430.      case GADGET_DATA_TYPE_SLIDER :
  431.  
  432.         /* Init slider data */
  433.         sl      = (struct SliderData *)buffer;
  434.         buffer += sizeof(struct SliderData);
  435.         break;
  436.  
  437.      case GADGET_DATA_TYPE_SCROLLER :
  438.  
  439.         /* Calc minimum dimensions of scroller gadget */
  440.         if (!(flags & GADGET_DATA_FLAG_SCROLLER_NO_ARROWS)) {
  441.            xmin = IMAGE_ARROW_WIDTH + IMAGE_HORIZ_OFFSET + xoffset;
  442.            ymin = IMAGE_ARROW_HEIGHT + IMAGE_VERT_OFFSET + yoffset;
  443.            if (flags & GADGET_DATA_FLAG_ORIENTATION_VERT) {
  444.           if (width < xmin) {
  445.              width = xmin;
  446.           }
  447.           if (height < 3 * ymin) {
  448.              height = 3 * ymin;
  449.           }
  450.            } else {
  451.           if (width < 3 * xmin) {
  452.              width = 3 * xmin;
  453.           }
  454.           if (height < ymin) {
  455.              height = ymin;
  456.           }
  457.            }
  458.         }
  459.  
  460.         /* Init scroller data */
  461.         sc      = (struct ScrollerData *)buffer;
  462.         buffer += sizeof(struct ScrollerData);
  463.         break;
  464.  
  465.      case GADGET_DATA_TYPE_CYCLE :
  466.  
  467.         /* Init cycle data */
  468.         cy      = (struct CycleData *)buffer;
  469.         buffer += sizeof(struct CycleData);
  470.         break;
  471.  
  472.      case GADGET_DATA_TYPE_COUNT :
  473.  
  474.         /* Init count data */
  475.         co      = (struct CountData *)buffer;
  476.         buffer += sizeof(struct CountData);
  477.         break;
  478.  
  479.      case GADGET_DATA_TYPE_LISTVIEW :
  480.  
  481.         /* Calc minimum dimension of list view gadget */
  482.         xmin = IMAGE_ARROW_WIDTH + IMAGE_HORIZ_OFFSET + xoffset;
  483.         ymin = IMAGE_ARROW_HEIGHT + IMAGE_VERT_OFFSET + yoffset;
  484.         if (height < 3 * ymin) {
  485.            height = 3 * ymin;
  486.         }
  487.         spacing = gd->gd_SpecialData.gd_ListViewData.gd_ListViewSpacing;
  488.         yinc    = text_height + spacing;
  489.         num     = (height - 2 * yoffset + spacing) / yinc;
  490.         height  = num * yinc + 2 * yoffset;
  491.  
  492.         /* Init list view data */
  493.         lv      = (struct ListViewData *)buffer;
  494.         buffer += sizeof(struct ListViewData);
  495.         break;
  496.  
  497.      case GADGET_DATA_TYPE_PALETTE :
  498.  
  499.         /* Calc dimension of color squares of palette */
  500.         min  = gd->gd_SpecialData.gd_PaletteData.gd_PaletteColorOffset;
  501.         max  = 1L << gd->gd_SpecialData.gd_PaletteData.gd_PaletteDepth;
  502.         xnum = max;   /* start with all squares in a horizontal line */
  503.         ynum = 1;
  504.         while (xnum > 1 && (width / xnum) / 2 < height / ynum) {
  505.            xnum /= 2;
  506.            ynum *= 2;
  507.         }
  508.         if (!(flags & GADGET_DATA_FLAG_PALETTE_NO_INDICATOR)) {
  509.  
  510.            /* Insert color indicator */
  511.            if (flags & GADGET_DATA_FLAG_PALETTE_INDICATOR_TOP) {
  512.           ynum++;
  513.            } else {
  514.           xnum++;
  515.            }
  516.         }
  517.  
  518.         /* Calc gadget dimension */
  519.         if (xnum == 1) {
  520.            xmin = width;
  521.         } else {
  522.            xmin  = (width - 2 * (xnum - 1)) / xnum;
  523.            width = xmin * xnum + 2 * (xnum - 1);
  524.         }
  525.         if (ynum == 1) {
  526.            ymin = height;
  527.         } else {
  528.            ymin   = (height - 1 * (ynum - 1)) / ynum;
  529.            height = ymin * ynum + 1 * (ynum - 1);
  530.         }
  531.  
  532.         /* Init palette data */
  533.         pd      = (struct PaletteData *)buffer;
  534.         buffer += sizeof(struct PaletteData);
  535.         break;
  536.       }
  537.  
  538.       /* Init gadget */
  539.       switch (type) {
  540.      case GADGET_DATA_TYPE_BUTTON :
  541.         buffer = init_extended_gadget(egad, buffer, gl, gd, i,
  542.             EXTENDED_GADGET_TYPE_BUTTON, left_edge, top_edge, width,
  543.                                     height);
  544.         break;
  545.  
  546.      case GADGET_DATA_TYPE_CHECK :
  547.         buffer = init_extended_gadget(egad, buffer, gl, gd, i,
  548.              EXTENDED_GADGET_TYPE_CHECK, left_edge, top_edge, width,
  549.                                     height);
  550.         break;
  551.  
  552.      case GADGET_DATA_TYPE_MX :
  553.  
  554.         /* Init all mx gadgets */
  555.         text = gd->gd_SpecialData.gd_MXData.gd_MXTextArray;
  556.         for (j = 0; j < num; j++, text++) {
  557.            buffer = init_extended_gadget(egad, buffer, gl, gd, i,
  558.             EXTENDED_GADGET_TYPE_MX, left_edge, top_edge, width,
  559.                                     height);
  560.            buffer = init_mx_text(egad, buffer, get_language_text(*text,
  561.                gl->gl_LanguageTextArray), width, height, flags, ta);
  562.            egad->eg_Gadget.GadgetID = j;   /* num of mx gadget */
  563.            if (j < (num - 1)) {   /* another mx gadget ? */
  564.           top_edge += yinc;
  565.           egad      = egad->eg_NextGadget =
  566.                         (struct ExtendedGadget *)buffer;
  567.           buffer   += sizeof(struct ExtendedGadget);
  568.            }
  569.         }
  570.  
  571.         /* Calc border offsets first - need old height */
  572.         if (!(flags & GADGET_DATA_FLAG_NO_BORDER)) {
  573.            if (flags & GADGET_DATA_FLAG_TEXT_LEFT) {
  574.           left_edge = -(max_width + xoffset + 8);
  575.            } else {
  576.           left_edge = -xoffset;   /* default right */
  577.            }
  578.            if (text_height > height) {
  579.           top_edge = -((text_height - height) / 2 + yoffset);
  580.            } else {
  581.           top_edge = -yoffset;
  582.            }
  583.         }
  584.  
  585.         /* Calc border dimension and draw it */
  586.         width += max_width + 2 * xoffset + 8;
  587.         height = yinc * num + 2 * yoffset -
  588.                   gd->gd_SpecialData.gd_MXData.gd_MXSpacing;
  589.         if (!(flags & GADGET_DATA_FLAG_NO_BORDER)) {
  590.            first_egad->eg_Render = (APTR)buffer;
  591.            buffer                = init_border(ri, buffer, left_edge,
  592.              top_edge, width, height, BORDER_DATA_TYPE_BOX1_IN);
  593.            first_egad->eg_Flags |= EXTENDED_GADGET_FLAG_RENDER_BORDER;
  594.         }
  595.         break;
  596.  
  597.      case GADGET_DATA_TYPE_STRING :
  598.         buffer = init_extended_gadget(egad, buffer, gl, gd, i,
  599.             EXTENDED_GADGET_TYPE_STRING, left_edge, top_edge, width,
  600.                                     height);
  601.         break;
  602.  
  603.      case GADGET_DATA_TYPE_INTEGER :
  604.         buffer = init_extended_gadget(egad, buffer, gl, gd, i,
  605.            EXTENDED_GADGET_TYPE_INTEGER, left_edge, top_edge, width,
  606.                                     height);
  607.         break;
  608.  
  609.      case GADGET_DATA_TYPE_SLIDER :
  610.  
  611.         /* Init slider data */
  612.         sl->sl_Min = gd->gd_SpecialData.gd_SliderData.gd_SliderMin;
  613.         sl->sl_Max = gd->gd_SpecialData.gd_SliderData.gd_SliderMax;
  614.         buffer     = init_extended_gadget(egad, buffer, gl, gd, i,
  615.               EXTENDED_GADGET_TYPE_SLIDER_PROP, left_edge, top_edge,
  616.                                  width, height);
  617.         break;
  618.  
  619.      case GADGET_DATA_TYPE_SCROLLER :
  620.  
  621.         /* Init scroller data */
  622.         sc->sc_Total   = gd->gd_SpecialData.gd_ScrollerData.gd_ScrollerTotal;
  623.         sc->sc_Visible = gd->gd_SpecialData.gd_ScrollerData.gd_ScrollerVisible;
  624.  
  625.         /* Init scroller gadgets */
  626.         if (flags & GADGET_DATA_FLAG_SCROLLER_NO_ARROWS) {
  627.            buffer = init_extended_gadget(egad, buffer, gl, gd, i,
  628.                   EXTENDED_GADGET_TYPE_SCROLLER_PROP, left_edge,
  629.                            top_edge, width, height);
  630.         } else {
  631.            if (flags & GADGET_DATA_FLAG_ORIENTATION_VERT) {
  632.  
  633.           /* Create vertical scroller - prop gadget first */
  634.           buffer = init_extended_gadget(egad, buffer, gl, gd, i,
  635.                   EXTENDED_GADGET_TYPE_SCROLLER_PROP, left_edge,
  636.                   top_edge, width, height - 2 * (ymin + 1));
  637.           /* Init scroller up arrow gadget */
  638.           egad    = egad->eg_NextGadget = (struct ExtendedGadget *)
  639.                                      buffer;
  640.           buffer += sizeof(struct ExtendedGadget);
  641.           buffer  = init_extended_gadget(egad, buffer, gl, gd, i,
  642.                 EXTENDED_GADGET_TYPE_SCROLLER_UP, left_edge,
  643.                  top_edge + height - 2 * ymin - 1, width, ymin);
  644.           /* Change type of vertical scroller arrow gadget for correct counting */
  645.           egad->eg_Type = EXTENDED_GADGET_TYPE_SCROLLER_DOWN;
  646.  
  647.           /* Init scroller down arrow gadget */
  648.           egad    = egad->eg_NextGadget = (struct ExtendedGadget *)
  649.                                      buffer;
  650.           buffer += sizeof(struct ExtendedGadget);
  651.           buffer  = init_extended_gadget(egad, buffer, gl, gd, i,
  652.                   EXTENDED_GADGET_TYPE_SCROLLER_DOWN, left_edge,
  653.                      top_edge + height - ymin, width, ymin);
  654.           /* Change type of vertical scroller arrow gadget for correct counting */
  655.           egad->eg_Type = EXTENDED_GADGET_TYPE_SCROLLER_UP;
  656.            } else {
  657.  
  658.           /* Create horizontal scroller - prop gadget first */
  659.           buffer = init_extended_gadget(egad, buffer, gl, gd, i,
  660.                   EXTENDED_GADGET_TYPE_SCROLLER_PROP, left_edge,
  661.                   top_edge, width - 2 * (xmin + 1), height);
  662.           /* Init scroller left arrow gadget */
  663.           egad    = egad->eg_NextGadget = (struct ExtendedGadget *)
  664.                                      buffer;
  665.           buffer += sizeof(struct ExtendedGadget);
  666.           buffer  = init_extended_gadget(egad, buffer, gl, gd, i,
  667.                  EXTENDED_GADGET_TYPE_SCROLLER_LEFT, left_edge +
  668.                   width - 2 * xmin - 1, top_edge, xmin, height);
  669.           /* Init scroller right arrow gadget */
  670.           egad    = egad->eg_NextGadget = (struct ExtendedGadget *)
  671.                                      buffer;
  672.           buffer += sizeof(struct ExtendedGadget);
  673.           buffer  = init_extended_gadget(egad, buffer, gl, gd, i,
  674.                 EXTENDED_GADGET_TYPE_SCROLLER_RIGHT, left_edge +
  675.                       width - xmin, top_edge, xmin, height);
  676.            }
  677.         }
  678.         break;
  679.  
  680.      case GADGET_DATA_TYPE_CYCLE :
  681.  
  682.         /* Count entries and calc max width of cycle text array */
  683.                text = gd->gd_SpecialData.gd_CycleData.gd_CycleTextArray;
  684.         num  = max_width = 0;
  685.         while (*text) {
  686.            itext.IText = (UBYTE *)get_language_text(*text++,
  687.                           gl->gl_LanguageTextArray);
  688.            if ((len = IntuiTextLength(&itext)) > max_width) {
  689.           max_width = len;
  690.            }
  691.            num++;
  692.         }
  693.  
  694.         /* Init cycle data */
  695.         image              = &ri->ri_Images[IMAGE_CYCLE];
  696.         xmin               = image->LeftEdge + image->Width +
  697.                                 xoffset + 4;
  698.         cy->cy_LeftEdge    = left_edge + xmin + (SHORT)(width -
  699.                           max_width - xmin - 4) / 2;
  700.         cy->cy_TopEdge     = top_edge + (SHORT)(height - text_height) / 2;
  701.         cy->cy_Width       = max_width;
  702.         cy->cy_Height      = text_height;
  703.         cy->cy_EntryHeight = text_height +
  704.                 gd->gd_SpecialData.gd_CycleData.gd_CycleSpacing;
  705.         cy->cy_TextArray   = gd->gd_SpecialData.gd_CycleData.gd_CycleTextArray;
  706.         cy->cy_TextEntries = num;
  707.         buffer             = init_extended_gadget(egad, buffer, gl, gd,
  708.           i, EXTENDED_GADGET_TYPE_CYCLE, left_edge, top_edge, width,
  709.                                     height);
  710.         break;
  711.  
  712.      case GADGET_DATA_TYPE_COUNT :
  713.  
  714.         /* Calc max width of count value */
  715.         min = gd->gd_SpecialData.gd_CountData.gd_CountMin;
  716.         max = gd->gd_SpecialData.gd_CountData.gd_CountMax;
  717.         if (flags & GADGET_DATA_FLAG_COUNT_SIGNED_DEC) {
  718.            len       = convert_signed_dec((LONG)min, (BYTE *)NULL, 0);
  719.            max_width = convert_signed_dec((LONG)max, (BYTE *)NULL, 0);
  720.         } else {
  721.            len       = convert_unsigned_dec(min, (BYTE *)NULL, 0);
  722.            max_width = convert_unsigned_dec(max, (BYTE *)NULL, 0);
  723.         }
  724.         if (len > max_width) {
  725.            max_width = len;
  726.         }
  727.         itext.IText = (UBYTE *)"8";
  728.         max_width  *= IntuiTextLength(&itext);
  729.  
  730.         /* Init count data */
  731.         co->co_LeftEdge = left_edge + (SHORT)(width - max_width) / 2;
  732.         co->co_TopEdge  = top_edge + (SHORT)(height - text_height) / 2;
  733.         co->co_Width    = max_width;
  734.         co->co_Height   = text_height;
  735.         co->co_Min      = min;
  736.         co->co_Max      = max;
  737.         buffer          = init_extended_gadget(egad, buffer, gl, gd, i,
  738.              EXTENDED_GADGET_TYPE_COUNT, left_edge, top_edge, width,
  739.                                     height);
  740.         break;
  741.  
  742.      case GADGET_DATA_TYPE_LISTVIEW :
  743.  
  744.         /* Init list view data */
  745.         lv->lv_LeftEdge       = left_edge + xoffset;
  746.         lv->lv_TopEdge        = top_edge + yoffset;
  747.         lv->lv_Width          = width - 2 * xoffset - xmin - 2;
  748.         lv->lv_Height         = height - 2 * yoffset;
  749.         lv->lv_VisibleEntries = num;
  750.         lv->lv_EntryHeight    = yinc;
  751.  
  752.         /* Create vertical scroller - prop gadget first */
  753.         left_edge += width - xmin;
  754.         buffer     = init_extended_gadget(egad, buffer, gl, gd, i,
  755.             EXTENDED_GADGET_TYPE_LISTVIEW_PROP, left_edge, top_edge,
  756.                          xmin, height - 2 * (ymin + 1));
  757.         /* Create entry field border */
  758.         if (!(flags & GADGET_DATA_FLAG_NO_BORDER)) {
  759.            USHORT border_type;
  760.  
  761.            ((struct Border *)egad->eg_Render)->NextBorder->NextBorder =
  762.                             (struct Border *)buffer;
  763.            if (flags & GADGET_DATA_FLAG_LISTVIEW_READ_ONLY) {
  764.           border_type = BORDER_DATA_TYPE_BOX1_IN;
  765.            } else {
  766.           border_type = BORDER_DATA_TYPE_BOX1_OUT;
  767.            }
  768.            buffer = init_border(ri, buffer, -(width + xoffset - xmin),
  769.                -yoffset, width - xmin - 2, height, border_type);
  770.         }
  771.  
  772.         /* Init list view up arrow gadget */
  773.         egad    = egad->eg_NextGadget = (struct ExtendedGadget *)buffer;
  774.         buffer += sizeof(struct ExtendedGadget);
  775.         buffer  = init_extended_gadget(egad, buffer, gl, gd, i,
  776.              EXTENDED_GADGET_TYPE_LISTVIEW_UP, left_edge, top_edge +
  777.                      height - 2 * ymin - 1, xmin, ymin);
  778.         /* Init list view down arrow gadget */
  779.         egad    = egad->eg_NextGadget = (struct ExtendedGadget *)buffer;
  780.         buffer += sizeof(struct ExtendedGadget);
  781.         buffer  = init_extended_gadget(egad, buffer, gl, gd, i,
  782.            EXTENDED_GADGET_TYPE_LISTVIEW_DOWN, left_edge, top_edge +
  783.                          height - ymin, xmin, ymin);
  784.         /* Init list view entry gadgets */
  785.         if (!(flags & GADGET_DATA_FLAG_LISTVIEW_READ_ONLY)) {
  786.            left_edge = lv->lv_LeftEdge;
  787.            top_edge  = lv->lv_TopEdge;
  788.            for (j = 0; j < num; j++, top_edge += yinc) {
  789.           egad            = egad->eg_NextGadget =
  790.                         (struct ExtendedGadget *)buffer;
  791.           buffer         += sizeof(struct ExtendedGadget);
  792.           buffer          = init_extended_gadget(egad, buffer, gl,
  793.                  gd, i, EXTENDED_GADGET_TYPE_LISTVIEW_ENTRY,
  794.                    left_edge, top_edge, lv->lv_Width, yinc);
  795.           egad->eg_Gadget.GadgetID = j;   /* num of entry gadget */
  796.            }
  797.         }
  798.         break;
  799.  
  800.      case GADGET_DATA_TYPE_PALETTE :
  801.  
  802.         /* Init palette data */
  803.         pd->pd_ColorOffset = min;
  804.         pd->pd_MaxColors   = max;
  805.  
  806.         /* Build color indicator */
  807.         if (!(flags & GADGET_DATA_FLAG_PALETTE_NO_INDICATOR)) {
  808.            if (flags & GADGET_DATA_FLAG_PALETTE_INDICATOR_TOP) {
  809.           buffer    = init_extended_gadget(egad, buffer, gl, gd, i,
  810.               EXTENDED_GADGET_TYPE_PALETTE_INDICATOR, left_edge,
  811.                              top_edge, width, ymin);
  812.           top_edge += ymin + 1;
  813.           ynum--;
  814.            } else {
  815.           buffer     = init_extended_gadget(egad, buffer, gl, gd, i,
  816.               EXTENDED_GADGET_TYPE_PALETTE_INDICATOR, left_edge,
  817.                             top_edge, xmin, height);
  818.           left_edge += xmin + 2;
  819.           xnum--;
  820.            }
  821.            egad    = egad->eg_NextGadget = (struct ExtendedGadget *)
  822.                                      buffer;
  823.            buffer += sizeof(struct ExtendedGadget);
  824.         }
  825.  
  826.         /* Build color gadgets */
  827.         num = gd->gd_SpecialData.gd_PaletteData.gd_PaletteColorOffset;
  828.         for (j = 0; j < ynum; j++, top_edge += ymin + 1) {
  829.            USHORT k, temp_left_edge = left_edge;
  830.  
  831.            for (k = 0; k < xnum; k++, temp_left_edge += xmin + 2) {
  832.           buffer = init_extended_gadget(egad, buffer, gl, gd, i,
  833.              EXTENDED_GADGET_TYPE_PALETTE_COLOR, temp_left_edge,
  834.                               top_edge, xmin, ymin);
  835.           ((struct Image *)egad->eg_Render)->PlaneOnOff = egad->eg_Gadget.GadgetID = num++;
  836.           if (j < (ynum - 1) || k < (xnum - 1)) {
  837.              egad    = egad->eg_NextGadget = (struct ExtendedGadget *)
  838.                                      buffer;
  839.              buffer += sizeof(struct ExtendedGadget);
  840.           }
  841.            }
  842.         }
  843.         break;
  844.       }
  845.  
  846.       /* Save absolut gadget dimension - needed by editor */
  847.       first_egad->eg_BorderWidth  = width;
  848.       first_egad->eg_BorderHeight = height;
  849.  
  850.       /* Init text and images */
  851.       if (gd->gd_Text) {
  852.      init_gadget_text(first_egad, get_language_text(gd->gd_Text,
  853.                gl->gl_LanguageTextArray), width, height, flags, ta);
  854.       }
  855.       if (image_buffer && type == GADGET_DATA_TYPE_BUTTON && (flags &
  856.                       GADGET_DATA_FLAG_BUTTON_IMAGE)) {
  857.      image_buffer = init_image_data(egad, image_buffer);
  858.       }
  859.  
  860.       /* Finally set gadget flags and special data */
  861.       set_gadget_attributes(gl, i, 0xffffffffL, flags,
  862.                     gd->gd_SpecialData.gd_Data.gd_Data1,
  863.                     gd->gd_SpecialData.gd_Data.gd_Data2,
  864.                        gd->gd_SpecialData.gd_Data.gd_Data3);
  865.    }
  866. }
  867.     /* Init extended gadget */
  868.  
  869.    STATIC BYTE *
  870. init_extended_gadget(struct ExtendedGadget  *egad, BYTE *buffer,
  871.       struct GadgetList  *gl, struct GadgetData  *gd, USHORT data_entry,
  872.            USHORT type, USHORT left_edge, USHORT top_edge, USHORT width,
  873.                                   USHORT height)
  874. {
  875.    struct RenderInfo  *ri = gl->gl_RenderInfo;
  876.    struct Gadget      *gad = &egad->eg_Gadget;
  877.    struct StringInfo  *sinfo;
  878.    struct PropInfo    *pinfo;
  879.    struct Image       *image;
  880.    ULONG  flags = gd->gd_Flags;
  881.    USHORT len;
  882.  
  883.    /* If monochrome display then set HIGHCOMP flag */
  884.    if (ri->ri_ScreenDepth == 1) {
  885.       flags |= GADGET_DATA_FLAG_HIGH_COMP;
  886.    }
  887.  
  888.    /* Init extended gadget */
  889.    egad->eg_Type       = type;
  890.    egad->eg_Flags      = 0;
  891.    egad->eg_DataType   = gd->gd_Type;
  892.    egad->eg_DataEntry  = data_entry;
  893.    egad->eg_DataFlags  = flags;
  894.    egad->eg_GadgetList = gl;
  895.  
  896.    /* Init normal gadget */
  897.    gad->LeftEdge      = left_edge;
  898.    gad->TopEdge       = top_edge;
  899.    gad->Width         = width;
  900.    gad->Height        = height;
  901.    gad->MutualExclude = ISUP_ID;
  902.    switch (type) {
  903.       case EXTENDED_GADGET_TYPE_BUTTON :
  904.      gad->GadgetType = BOOLGADGET;
  905.      if (flags & GADGET_DATA_FLAG_BUTTON_TOGGLE) {
  906.         gad->Activation = RELVERIFY | TOGGLESELECT;
  907.         if (flags & GADGET_DATA_FLAG_BUTTON_IMAGE) {
  908.            gad->Flags = GADGIMAGE | GADGHIMAGE;
  909.            buffer     = init_gadget_image(egad, gd, buffer);
  910.         }
  911.      } else {
  912.         gad->Activation = RELVERIFY;
  913.         if (flags & GADGET_DATA_FLAG_BUTTON_IMAGE) {
  914.            if ((flags & GADGET_DATA_FLAG_NO_BORDER) &&
  915.                     !(flags & GADGET_DATA_FLAG_HIGH_COMP)) {
  916.           gad->Flags = GADGIMAGE | GADGHIMAGE;
  917.           buffer     = init_gadget_image(egad, gd, buffer);
  918.            } else {
  919.           buffer          = init_gadget_image(egad, gd, buffer);
  920.           egad->eg_Flags |= EXTENDED_GADGET_FLAG_RENDER_IMAGE;
  921.            }
  922.         }
  923.      }
  924.      break;
  925.  
  926.       case EXTENDED_GADGET_TYPE_CHECK :
  927.       case EXTENDED_GADGET_TYPE_MX :
  928.      gad->GadgetType = BOOLGADGET;
  929.      gad->Activation = TOGGLESELECT | GADGIMMEDIATE;
  930.      gad->Flags      = GADGIMAGE | GADGHIMAGE;
  931.      if (type == EXTENDED_GADGET_TYPE_CHECK) {
  932.         gad->GadgetRender = (APTR)&ri->ri_Images[IMAGE_CHECK_UNSELECTED];
  933.         gad->SelectRender = (APTR)&ri->ri_Images[IMAGE_CHECK_SELECTED];
  934.      } else {
  935.         gad->GadgetRender = (APTR)&ri->ri_Images[IMAGE_KNOB_UNSELECTED];
  936.         gad->SelectRender = (APTR)&ri->ri_Images[IMAGE_KNOB_SELECTED];
  937.      }
  938.      break;
  939.  
  940.       case EXTENDED_GADGET_TYPE_STRING :
  941.       case EXTENDED_GADGET_TYPE_INTEGER :
  942.      gad->GadgetType = STRGADGET;
  943.      if (type == EXTENDED_GADGET_TYPE_STRING) {
  944.         gad->Activation = RELVERIFY;
  945.      } else {
  946.         gad->Activation = RELVERIFY | LONGINT;
  947.      }
  948.      gad->Flags       = GADGHCOMP;
  949.      gad->SpecialInfo = (APTR)buffer;
  950.  
  951.      /* Calc size of input buffer */
  952.      if (type == GADGET_DATA_TYPE_STRING) {
  953.         len = gd->gd_SpecialData.gd_InputData.gd_InputLen;
  954.         if (flags & (GADGET_DATA_FLAG_STRING_UNSIGNED_DEC |
  955.                     GADGET_DATA_FLAG_STRING_SIGNED_DEC |
  956.                            GADGET_DATA_FLAG_STRING_HEX |
  957.                          GADGET_DATA_FLAG_STRING_BIN)) {
  958.            if (len < (MAX_BIN_NUM_DIGITS + 1)) {
  959.           len = MAX_BIN_NUM_DIGITS + 1;   /* identifier `%' + number */
  960.            }
  961.         }
  962.      } else {
  963.         len = MAX_DEC_NUM_DIGITS;
  964.      }
  965.  
  966.      /* Init string info */
  967.      sinfo           = (struct StringInfo *)buffer;
  968.      buffer         += sizeof(struct StringInfo);
  969.      sinfo->Buffer   = (UBYTE *)buffer;
  970.      sinfo->MaxChars = len + 1;
  971.      if (len & 1) {   /* input len odd */
  972.         buffer += len + 1;
  973.      } else {
  974.         buffer += len + 2;
  975.      }
  976.      break;
  977.  
  978.       case EXTENDED_GADGET_TYPE_SLIDER_PROP :
  979.       case EXTENDED_GADGET_TYPE_SCROLLER_PROP :
  980.       case EXTENDED_GADGET_TYPE_LISTVIEW_PROP :
  981.      gad->GadgetType   = PROPGADGET;
  982.      gad->Activation   = GADGIMMEDIATE | RELVERIFY | FOLLOWMOUSE;
  983.      gad->Flags        = GADGHNONE;
  984.      gad->GadgetRender = (APTR)buffer;   /* needed for auto knob */
  985.      buffer           += sizeof(struct Image);
  986.      gad->SpecialInfo  = (APTR)buffer;
  987.  
  988.      /* Init prop info */
  989.      pinfo   = (struct PropInfo *)buffer;
  990.      buffer += sizeof(struct PropInfo);
  991.      if (type == EXTENDED_GADGET_TYPE_LISTVIEW_PROP || flags &
  992.                     GADGET_DATA_FLAG_ORIENTATION_VERT) {
  993.         pinfo->Flags = AUTOKNOB | FREEVERT | PROPBORDERLESS;
  994.      } else {
  995.         pinfo->Flags = AUTOKNOB | FREEHORIZ | PROPBORDERLESS;
  996.      }
  997.      break;
  998.  
  999.       case EXTENDED_GADGET_TYPE_SCROLLER_LEFT :
  1000.       case EXTENDED_GADGET_TYPE_SCROLLER_RIGHT :
  1001.       case EXTENDED_GADGET_TYPE_SCROLLER_UP :
  1002.       case EXTENDED_GADGET_TYPE_SCROLLER_DOWN :
  1003.       case EXTENDED_GADGET_TYPE_LISTVIEW_UP :
  1004.       case EXTENDED_GADGET_TYPE_LISTVIEW_DOWN :
  1005.      gad->GadgetType = BOOLGADGET;
  1006.      gad->Activation = GADGIMMEDIATE | RELVERIFY;
  1007.      switch (type) {
  1008.         case EXTENDED_GADGET_TYPE_SCROLLER_LEFT :
  1009.            egad->eg_Render = (APTR)&ri->ri_Images[IMAGE_ARROW_LEFT];
  1010.            break;
  1011.  
  1012.         case EXTENDED_GADGET_TYPE_SCROLLER_RIGHT :
  1013.            egad->eg_Render = (APTR)&ri->ri_Images[IMAGE_ARROW_RIGHT];
  1014.            break;
  1015.  
  1016.         case EXTENDED_GADGET_TYPE_SCROLLER_UP :
  1017.         case EXTENDED_GADGET_TYPE_LISTVIEW_UP :
  1018.            egad->eg_Render = (APTR)&ri->ri_Images[IMAGE_ARROW_UP];
  1019.            break;
  1020.  
  1021.         case EXTENDED_GADGET_TYPE_SCROLLER_DOWN :
  1022.         case EXTENDED_GADGET_TYPE_LISTVIEW_DOWN :
  1023.            egad->eg_Render = (APTR)&ri->ri_Images[IMAGE_ARROW_DOWN];
  1024.            break;
  1025.      }
  1026.      egad->eg_Flags |= EXTENDED_GADGET_FLAG_RENDER_IMAGE;
  1027.      break;
  1028.  
  1029.       case EXTENDED_GADGET_TYPE_CYCLE :
  1030.      gad->GadgetType = BOOLGADGET;
  1031.      gad->Activation = TOGGLESELECT | GADGIMMEDIATE;
  1032.      egad->eg_Render = (APTR)&ri->ri_Images[IMAGE_CYCLE];
  1033.      egad->eg_Flags |= EXTENDED_GADGET_FLAG_RENDER_IMAGE;
  1034.      break;
  1035.  
  1036.       case EXTENDED_GADGET_TYPE_COUNT :
  1037.      gad->GadgetType = BOOLGADGET;
  1038.      gad->Activation = TOGGLESELECT | GADGIMMEDIATE;
  1039.      egad->eg_Render = (APTR)&ri->ri_Images[IMAGE_COUNT_LEFT];
  1040.      egad->eg_Flags |= EXTENDED_GADGET_FLAG_RENDER_IMAGE;
  1041.      break;
  1042.  
  1043.       case EXTENDED_GADGET_TYPE_LISTVIEW_ENTRY :
  1044.      gad->GadgetType = BOOLGADGET;
  1045.      gad->Activation = RELVERIFY;
  1046.      gad->Flags      = GADGHCOMP;
  1047.      break;
  1048.  
  1049.       case EXTENDED_GADGET_TYPE_PALETTE_INDICATOR :
  1050.       case EXTENDED_GADGET_TYPE_PALETTE_COLOR :
  1051.      gad->GadgetType = BOOLGADGET;
  1052.      gad->Activation = RELVERIFY;
  1053.  
  1054.      /* Init image */
  1055.      image   = (struct Image *)buffer;
  1056.      buffer += sizeof(struct Image);
  1057.      if (flags & GADGET_DATA_FLAG_NO_BORDER) {
  1058.         image->Width    = width;
  1059.         image->Height   = height;
  1060.      } else {
  1061.         image->LeftEdge = 0;
  1062.         image->TopEdge  = 0;
  1063.         image->Width    = width - 2 * 4;
  1064.         image->Height   = height - 2 * 2;
  1065.      }
  1066.      image->Depth    = ri->ri_ScreenDepth;
  1067.      egad->eg_Render = (APTR)image;
  1068.      egad->eg_Flags |= EXTENDED_GADGET_FLAG_RENDER_IMAGE;
  1069.      break;
  1070.    }
  1071.    if (flags & GADGET_DATA_FLAG_DISABLED) {
  1072.       gad->Flags |= GADGDISABLED;
  1073.    }
  1074.    return(init_gadget_border(buffer, ri, egad, flags));
  1075. }
  1076.     /* Init gadget border */
  1077.  
  1078.    STATIC BYTE *
  1079. init_gadget_border(BYTE *buffer, struct RenderInfo  *ri,
  1080.                   struct ExtendedGadget  *egad, ULONG flags)
  1081. {
  1082.    struct Gadget  *gad = &egad->eg_Gadget;
  1083.    USHORT width = gad->Width, height = gad->Height;
  1084.  
  1085.    switch (egad->eg_Type) {
  1086.       case EXTENDED_GADGET_TYPE_BUTTON :
  1087.      if ((flags & GADGET_DATA_FLAG_BUTTON_TOGGLE) &&
  1088.                   (flags & GADGET_DATA_FLAG_BUTTON_IMAGE)) {
  1089.         /* Init non toggle border out */
  1090.         if (!(flags & GADGET_DATA_FLAG_NO_BORDER)) {
  1091.            egad->eg_Render = (APTR)buffer;
  1092.            egad->eg_Flags |= EXTENDED_GADGET_FLAG_RENDER_BORDER;
  1093.            buffer          = init_border(ri, buffer, 0, 0, width,
  1094.                      height, BORDER_DATA_TYPE_BOX1_OUT);
  1095.         }
  1096.      } else {
  1097.  
  1098.         /* Init toggle border */
  1099.         if (flags & GADGET_DATA_FLAG_HIGH_COMP) {
  1100.            gad->Flags |= GADGHCOMP;
  1101.            if (!(flags & GADGET_DATA_FLAG_NO_BORDER)) {
  1102.           gad->GadgetRender = (APTR)buffer;
  1103.           buffer            = init_border(ri, buffer, 0, 0, width,
  1104.                      height, BORDER_DATA_TYPE_BOX1_OUT);
  1105.            }
  1106.         } else {
  1107.            if (!(flags & GADGET_DATA_FLAG_NO_BORDER)) {
  1108.           gad->Flags       |= GADGHIMAGE;
  1109.           gad->GadgetRender = (APTR)buffer;
  1110.           buffer            = init_border(ri, buffer, 0, 0, width,
  1111.                      height, BORDER_DATA_TYPE_BOX1_OUT);
  1112.           gad->SelectRender = (APTR)buffer;
  1113.           buffer            = init_border(ri, buffer, 0, 0, width,
  1114.                       height, BORDER_DATA_TYPE_BOX1_IN);
  1115.            } else {
  1116.           if (!(gad->Flags & GADGHIMAGE)) {
  1117.              gad->Flags |= GADGHNONE;
  1118.           }
  1119.            }
  1120.         }
  1121.      }
  1122.      break;
  1123.  
  1124.       case EXTENDED_GADGET_TYPE_CHECK :
  1125.  
  1126.      /* Init non toggle border out */
  1127.      if (!(flags & GADGET_DATA_FLAG_NO_BORDER)) {
  1128.         egad->eg_Render = (APTR)buffer;
  1129.         egad->eg_Flags |= EXTENDED_GADGET_FLAG_RENDER_BORDER;
  1130.         buffer          = init_border(ri, buffer, 0, 0, width, height,
  1131.                          BORDER_DATA_TYPE_BOX1_OUT);
  1132.      }
  1133.      break;
  1134.  
  1135.       case EXTENDED_GADGET_TYPE_SCROLLER_LEFT :
  1136.       case EXTENDED_GADGET_TYPE_SCROLLER_RIGHT :
  1137.       case EXTENDED_GADGET_TYPE_SCROLLER_UP :
  1138.       case EXTENDED_GADGET_TYPE_SCROLLER_DOWN :
  1139.       case EXTENDED_GADGET_TYPE_LISTVIEW_UP :
  1140.       case EXTENDED_GADGET_TYPE_LISTVIEW_DOWN :
  1141.       case EXTENDED_GADGET_TYPE_CYCLE :
  1142.       case EXTENDED_GADGET_TYPE_COUNT :
  1143.       case EXTENDED_GADGET_TYPE_PALETTE_COLOR :
  1144.  
  1145.      /* Init toggle border */
  1146.      if (flags & GADGET_DATA_FLAG_HIGH_COMP) {
  1147.         gad->Flags |= GADGHCOMP;
  1148.         if (!(flags & GADGET_DATA_FLAG_NO_BORDER)) {
  1149.            gad->GadgetRender = (APTR)buffer;
  1150.            buffer            = init_border(ri, buffer, 0, 0,
  1151.                   width, height, BORDER_DATA_TYPE_BOX1_OUT);
  1152.         }
  1153.      } else {
  1154.         if (!(flags & GADGET_DATA_FLAG_NO_BORDER)) {
  1155.            gad->Flags       |= GADGHIMAGE;
  1156.            gad->GadgetRender = (APTR)buffer;
  1157.            buffer            = init_border(ri, buffer, 0, 0, width,
  1158.                      height, BORDER_DATA_TYPE_BOX1_OUT);
  1159.            gad->SelectRender = (APTR)buffer;
  1160.            buffer            = init_border(ri, buffer, 0, 0, width,
  1161.                       height, BORDER_DATA_TYPE_BOX1_IN);
  1162.         } else {
  1163.            gad->Flags |= GADGHNONE;
  1164.         }
  1165.      }
  1166.      break;
  1167.  
  1168.       case EXTENDED_GADGET_TYPE_PALETTE_INDICATOR :
  1169.  
  1170.      /* Init non toggle border in */
  1171.      gad->Flags |= GADGHNONE;
  1172.      if (!(flags & GADGET_DATA_FLAG_NO_BORDER)) {
  1173.         gad->GadgetRender = (APTR)buffer;
  1174.         buffer            = init_border(ri, buffer, 0, 0, width, height,
  1175.                           BORDER_DATA_TYPE_BOX1_IN);
  1176.      }
  1177.      break;
  1178.  
  1179.       case EXTENDED_GADGET_TYPE_STRING :
  1180.       case EXTENDED_GADGET_TYPE_INTEGER :
  1181.  
  1182.      /* Init input border */
  1183.      if (!(flags & GADGET_DATA_FLAG_NO_BORDER)) {
  1184.         gad->GadgetRender = (APTR)buffer;
  1185.         gad->LeftEdge    += 6;
  1186.         gad->TopEdge     += 3;
  1187.         gad->Width       -= 2 * 6;
  1188.         gad->Height      -= 2 * 3;
  1189.         buffer            = init_border(ri, buffer, -6, -3, width,
  1190.                      height, BORDER_DATA_TYPE_BOX2_OUT);
  1191.      }
  1192.      break;
  1193.  
  1194.       case EXTENDED_GADGET_TYPE_SLIDER_PROP :
  1195.       case EXTENDED_GADGET_TYPE_SCROLLER_PROP :
  1196.       case EXTENDED_GADGET_TYPE_LISTVIEW_PROP :
  1197.  
  1198.      /* Init prop border */
  1199.      if (!(flags & GADGET_DATA_FLAG_NO_BORDER)) {
  1200.         egad->eg_Render = (APTR)buffer;
  1201.         egad->eg_Flags |= EXTENDED_GADGET_FLAG_RENDER_BORDER;
  1202.         gad->LeftEdge  += 4;
  1203.         gad->TopEdge   += 2;
  1204.         gad->Width     -= 2 * 4;
  1205.         gad->Height    -= 2 * 2;
  1206.         buffer          = init_border(ri, buffer, -4, -2, width, height,
  1207.                          BORDER_DATA_TYPE_BOX1_OUT);
  1208.      }
  1209.      break;
  1210.    }
  1211.    return(buffer);
  1212. }
  1213.     /* Init gadget text */
  1214.  
  1215.    STATIC VOID
  1216. init_gadget_text(struct ExtendedGadget  *egad, BYTE *text, USHORT width,
  1217.                USHORT height, ULONG flags, struct TextAttr  *ta)
  1218. {
  1219.    /* Search hotkey in gadget text */
  1220.    if (flags & GADGET_DATA_FLAG_HOTKEY) {
  1221.       BYTE   *ptr = text;
  1222.       USHORT i;
  1223.  
  1224.       for (i = 0; *ptr; i++) {
  1225.      BYTE c;
  1226.  
  1227.      if (*ptr++ == '_' && (c = *ptr)) {
  1228.  
  1229.         /* Only printable characters are allowed as hotkeys */
  1230.         if ((c >= ' ' && c <= '~') || (c >= '¡' && c <= 0xff)) {
  1231.            egad->eg_Hotkey    = (USHORT)c;
  1232.            egad->eg_HotkeyPos = i + 1;
  1233.            egad->eg_Flags    |= EXTENDED_GADGET_FLAG_HOTKEY;
  1234.            break;
  1235.         }
  1236.      }
  1237.       }
  1238.    }
  1239.  
  1240.    /* Ignore text if no output is required */
  1241.    if (!(flags & GADGET_DATA_FLAG_NO_TEXT_OUTPUT)) {
  1242.       struct IntuiText  itext;
  1243.       SHORT  text_width, text_height, xoffset, yoffset, left_edge, top_edge;
  1244.       USHORT type = egad->eg_DataType;
  1245.  
  1246.       /* Calc text dimension */
  1247.       itext.IText     = (UBYTE *)text;
  1248.       itext.ITextFont = ta;
  1249.       text_width      = IntuiTextLength(&itext);
  1250.       if (egad->eg_Flags & EXTENDED_GADGET_FLAG_HOTKEY) {
  1251.      itext.IText = (UBYTE *)&hotkey_id[0];
  1252.      text_width -= IntuiTextLength(&itext);
  1253.       }
  1254.       text_height = ta->ta_YSize;
  1255.  
  1256.       /* Calc border offset */
  1257.       if (flags & GADGET_DATA_FLAG_NO_BORDER) {
  1258.      xoffset = 0;
  1259.      yoffset = 0;
  1260.       } else {
  1261.      switch (type) {
  1262.         case GADGET_DATA_TYPE_MX :
  1263.            xoffset = 8;
  1264.            yoffset = 4;
  1265.            break;
  1266.  
  1267.         case GADGET_DATA_TYPE_STRING :
  1268.         case GADGET_DATA_TYPE_INTEGER :
  1269.            xoffset = 6;
  1270.            yoffset = 3;
  1271.            break;
  1272.  
  1273.         case GADGET_DATA_TYPE_SLIDER :
  1274.         case GADGET_DATA_TYPE_SCROLLER :
  1275.         case GADGET_DATA_TYPE_LISTVIEW :
  1276.            xoffset = 4;
  1277.            yoffset = 2;
  1278.            break;
  1279.  
  1280.         default :
  1281.            xoffset = 0;
  1282.            yoffset = 0;
  1283.            break;
  1284.      }
  1285.       }
  1286.  
  1287.       /* Calc text pos */
  1288.       switch (type) {
  1289.      case GADGET_DATA_TYPE_MX :
  1290.         if (flags & GADGET_DATA_FLAG_TEXT_LEFT) {
  1291.            left_edge = -(width - egad->eg_Gadget.Width - xoffset -
  1292.                        (SHORT)(width - text_width) / 2);
  1293.         } else {
  1294.            left_edge = (SHORT)(width - text_width) / 2 - xoffset;
  1295.         }
  1296.         if (text_height > IMAGE_KNOB_HEIGHT) {
  1297.            top_edge = -((text_height - IMAGE_KNOB_HEIGHT) / 2);
  1298.         } else {
  1299.            top_edge = 0;
  1300.         }
  1301.         top_edge -= (text_height + yoffset + 4);
  1302.         break;
  1303.  
  1304.      case GADGET_DATA_TYPE_LISTVIEW :
  1305.         left_edge = -(width - egad->eg_Gadget.Width - xoffset -
  1306.                        (SHORT)(width - text_width) / 2);
  1307.         top_edge  = -(text_height + yoffset + 4);
  1308.         break;
  1309.  
  1310.      case GADGET_DATA_TYPE_PALETTE :
  1311.         left_edge = (SHORT)(width - text_width) / 2;
  1312.         top_edge  = -(text_height + 4);
  1313.         break;
  1314.  
  1315.      default :
  1316.  
  1317.         /* Calc horizontal pos */
  1318.         if (flags & GADGET_DATA_FLAG_TEXT_LEFT) {
  1319.            left_edge = -(text_width + xoffset + 8);
  1320.         } else {
  1321.            if (flags & GADGET_DATA_FLAG_TEXT_RIGHT) {
  1322.           left_edge = width - xoffset + 8;
  1323.            } else {
  1324.           left_edge = (SHORT)(width - 2 * xoffset - text_width) / 2;
  1325.            }
  1326.         }
  1327.  
  1328.         /* Calc vertical pos */
  1329.         if (flags & GADGET_DATA_FLAG_TEXT_ABOVE) {
  1330.            top_edge = -(text_height + yoffset + 4);
  1331.         } else {
  1332.            if (flags & GADGET_DATA_FLAG_TEXT_BELOW) {
  1333.           top_edge = height - yoffset + 4;
  1334.            } else {
  1335.           top_edge = (SHORT)(height - 2 * yoffset - text_height) / 2;
  1336.            }
  1337.         }
  1338.         break;
  1339.       }
  1340.  
  1341.       /* Save position and width of text */
  1342.       egad->eg_Text         = text;
  1343.       egad->eg_TextLeftEdge = left_edge;
  1344.       egad->eg_TextTopEdge  = top_edge;
  1345.       egad->eg_TextWidth    = text_width;
  1346.    }
  1347. }
  1348.     /* Init mutual exclude gadget text */
  1349.  
  1350.    STATIC BYTE *
  1351. init_mx_text(struct ExtendedGadget  *egad, BYTE *buffer, BYTE *text,
  1352.          USHORT width, USHORT height, ULONG flags, struct TextAttr  *ta)
  1353. {
  1354.    struct RenderInfo  *ri = egad->eg_GadgetList->gl_RenderInfo;
  1355.    struct IntuiText   *itext;
  1356.  
  1357.    itext            = (struct IntuiText *)buffer;
  1358.    buffer          += sizeof(struct IntuiText);
  1359.    itext->FrontPen  = (flags & GADGET_DATA_FLAG_TEXT_COLOR2 ?
  1360.                      ri->ri_TextPen2 : ri->ri_TextPen1);
  1361.    itext->BackPen   = ri->ri_BackPen;
  1362.    itext->DrawMode  = JAM2;
  1363.    itext->IText     = (UBYTE *)text;
  1364.    itext->ITextFont = ta;
  1365.    itext->TopEdge   = (SHORT)(height - ta->ta_YSize) / 2;
  1366.    if (flags & GADGET_DATA_FLAG_TEXT_LEFT) {
  1367.       itext->LeftEdge = -(IntuiTextLength(itext) + 8);
  1368.    } else {
  1369.       itext->LeftEdge = width + 8;   /* default right */
  1370.    }
  1371.    egad->eg_Gadget.GadgetText = itext;
  1372.    return(buffer);
  1373. }
  1374.     /* Check image for valid chip mem data */
  1375.  
  1376.    STATIC BOOL
  1377. check_gadget_image(struct Image  *image)
  1378. {
  1379.    BYTE *data;
  1380.    BOOL result;
  1381.  
  1382.    if ((data = (BYTE *)image->ImageData) && !(TypeOfMem(data) & MEMF_CHIP)) {
  1383.       result = FALSE;
  1384.    } else {
  1385.       result = TRUE;
  1386.    }
  1387.    return(result);
  1388. }
  1389.     /* Init gadget image */
  1390.  
  1391.    STATIC BYTE *
  1392. init_gadget_image(struct ExtendedGadget  *egad, struct GadgetData  *gd,
  1393.                                    BYTE *buffer)
  1394. {
  1395.    struct Gadget  *gad = &egad->eg_Gadget;
  1396.    struct Image   *image = gd->gd_SpecialData.gd_ButtonData.gd_ButtonNormalRender;
  1397.  
  1398.    if (gad->Flags & GADGIMAGE) {
  1399.       if (check_gadget_image(image) == FALSE) {
  1400.      egad->eg_Flags |= EXTENDED_GADGET_FLAG_NORMAL_IMAGE_COPY;
  1401.      CopyMem((BYTE *)image, buffer, (LONG)sizeof(struct Image));
  1402.      image   = (struct Image *)buffer;
  1403.      buffer += sizeof(struct Image);
  1404.       }
  1405.       gad->GadgetRender = (APTR)image;
  1406.       if (gad->Flags & GADGHIMAGE) {
  1407.      if (!(image = gd->gd_SpecialData.gd_ButtonData.gd_ButtonSelectRender)) {
  1408.         gad->Flags &= ~GADGHIGHBITS;
  1409.         gad->Flags |= GADGHNONE;
  1410.      } else {
  1411.         if (check_gadget_image(image) == FALSE) {
  1412.            egad->eg_Flags |= EXTENDED_GADGET_FLAG_SELECT_IMAGE_COPY;
  1413.            CopyMem((BYTE *)image, buffer, (LONG)sizeof(struct Image));
  1414.            image   = (struct Image *)buffer;
  1415.            buffer += sizeof(struct Image);
  1416.         }
  1417.         gad->SelectRender = (APTR)image;
  1418.      }
  1419.       }
  1420.    } else {
  1421.       if (check_gadget_image(image) == FALSE) {
  1422.      egad->eg_Flags |= EXTENDED_GADGET_FLAG_NORMAL_IMAGE_COPY;
  1423.      CopyMem((BYTE *)image, buffer, (LONG)sizeof(struct Image));
  1424.      image   = (struct Image *)buffer;
  1425.      buffer += sizeof(struct Image);
  1426.       }
  1427.       egad->eg_Render = (APTR)image;
  1428.    }
  1429.    return(buffer);
  1430. }
  1431.     /* Init image data - make chipmem copy if needed */
  1432.  
  1433.    STATIC BYTE *
  1434. init_image_data(struct ExtendedGadget  *egad, BYTE *buffer)
  1435. {
  1436.    struct Gadget  *gad = &egad->eg_Gadget;
  1437.    struct Image   *image;
  1438.    BYTE  *data;
  1439.    LONG  size;
  1440.    UBYTE flags = egad->eg_Flags;
  1441.  
  1442.    if (flags & EXTENDED_GADGET_FLAG_NORMAL_IMAGE_COPY) {
  1443.       if (flags & EXTENDED_GADGET_FLAG_RENDER_IMAGE) {
  1444.      image = (struct Image *)egad->eg_Render;
  1445.       } else {
  1446.      image = (struct Image *)gad->GadgetRender;
  1447.       }
  1448.       if ((data = (BYTE *)image->ImageData) && !(TypeOfMem(data) &
  1449.                                    MEMF_CHIP)) {
  1450.      size = (image->Width / 16 + (image->Width & 15 ? 1 : 0))
  1451.                      * image->Height * image->Depth * 2;
  1452.      CopyMem(data, buffer, size);
  1453.      image->ImageData = (UWORD *)buffer;
  1454.      buffer          += size;
  1455.       }
  1456.    }
  1457.    if (flags & EXTENDED_GADGET_FLAG_SELECT_IMAGE_COPY) {
  1458.       image = (struct Image *)gad->SelectRender;
  1459.       if ((data = (BYTE *)image->ImageData) && !(TypeOfMem(data) &
  1460.                                    MEMF_CHIP)) {
  1461.      size = (image->Width / 16 + (image->Width & 15 ? 1 : 0))
  1462.                      * image->Height * image->Depth * 2;
  1463.      CopyMem(data, buffer, size);
  1464.      image->ImageData = (UWORD *)buffer;
  1465.      buffer          += size;
  1466.       }
  1467.    }
  1468.    return(buffer);
  1469. }
  1470.